#include "importthread.h"

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDir>
#include <QFile>
#include <QVariant>

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmsr/dsrdoc.h"
#include <QDateTime>

ImportThread::ImportThread(const QString &srcDir, const QString &dbFile, QObject *parent):
    m_srcDir(srcDir),
    m_dbFile(dbFile),
    QThread(parent)
{

}

void ImportThread::run()
{
    QStringList ps, fs;
    ps += m_srcDir;
    while (!ps.isEmpty()) {
        QString d = ps.takeFirst();
        QStringList es = QDir(d).entryList(QDir::Dirs|QDir::NoDotAndDotDot);
        foreach (const QString &e, es) {
            ps += d + "/" + e;
        }
        es = QDir(d).entryList(QDir::Files);
        foreach (const QString &e, es) {
            fs += d + "/" + e;
        }
    }

    emit totalFiles(fs.size());

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(m_dbFile);
    if (!db.open()) {
        emit resultReady(false, db.lastError().text());
        return;
    }

    foreach (const QString &f, fs) {
        DcmFileFormat ff;
        OFCondition cond = ff.loadFile(f.toLocal8Bit().data());
        if (cond.bad()) {
            emit resultReady(false, cond.text());
            continue;
        }

        OFString val;
        QDateTime t;
        DcmDataset *dset = ff.getDataset();
        QSqlQuery query(db);
        query.prepare(QString("INSERT INTO StudyTable VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
        dset->findAndGetOFString(DCM_StudyInstanceUID, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_AccessionNumber, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientID, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientName, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientSex, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientBirthDate, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientAge, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_AdmissionID, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_StudyDate, val);
        t.setDate(QDate::fromString(val.c_str(), "yyyyMMdd"));
        dset->findAndGetOFString(DCM_StudyTime, val);
        t.setTime(QTime::fromString(QString(val.c_str()).left(6), "hhmmss"));
        query.addBindValue(t.toString("yyyy-MM-dd hh:mm:ss"));
        dset->findAndGetOFString(DCM_Modality, val);
        query.addBindValue(QString(val.c_str()));

        query.addBindValue(QObject::tr("No"));
        query.addBindValue(QObject::tr("No"));
        query.addBindValue(QObject::tr("No"));
        query.addBindValue(QObject::tr("No"));

        dset->findAndGetOFString(DCM_StudyDescription, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_RequestingPhysician, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PerformingPhysicianName, val);
        query.addBindValue(QString(val.c_str()));

        dset->findAndGetOFString(DCM_MedicalAlerts, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientSize, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientWeight, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientAddress, val);
        query.addBindValue(QString(val.c_str()));
        dset->findAndGetOFString(DCM_PatientTelephoneNumbers, val);
        query.addBindValue(QString(val.c_str()));
        query.exec();

        dset->findAndGetOFString(DCM_SOPClassUID, val);
        if (QString(val.c_str()) != UID_BasicTextSRStorage) {
            query.prepare(QString("INSERT INTO ImageTable VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"));
            dset->findAndGetOFString(DCM_SOPInstanceUID, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_SOPClassUID, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_SeriesInstanceUID, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_StudyInstanceUID, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_ReferencedSOPInstanceUID, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_InstanceNumber, val);
            query.addBindValue(QString(val.c_str()));
            dset->findAndGetOFString(DCM_ContentDate, val);
            t.setDate(QDate::fromString(val.c_str(), "yyyyMMdd"));
            dset->findAndGetOFString(DCM_ContentTime, val);
            t.setTime(QTime::fromString(QString(val.c_str()).left(6), "hhmmss"));
            query.addBindValue(t.toString("yyyy-MM-dd hh:mm:ss"));
            dset->findAndGetOFString(DCM_BodyPartExamined, val);
            query.addBindValue(QString(val.c_str()));
            query.addBindValue(QObject::tr("No"));
            query.addBindValue(QObject::tr("No"));
            dset->findAndGetOFString(DCM_SeriesDescription, val);
            query.addBindValue(QString(val.c_str()));
            query.addBindValue(m_srcDir.mid(m_srcDir.lastIndexOf("/")+1) + "/" + f.mid(m_srcDir.size()+1));
            if (query.exec()) {
                emit resultReady(true, "Import Ok.");
            } else {
                emit resultReady(false, query.lastError().text());
            }
        } else {
            DSRDocument doc;
            OFCondition cond = doc.read(*dset);
            if (cond.good()) {
                query.prepare(QString("INSERT INTO ReportTable VALUES(?,?,?,?,?,?,?,?,?)"));
                dset->findAndGetOFString(DCM_SOPInstanceUID, val);
                query.addBindValue(QString(val.c_str()));
                dset->findAndGetOFString(DCM_SeriesInstanceUID, val);
                query.addBindValue(QString(val.c_str()));
                dset->findAndGetOFString(DCM_StudyInstanceUID, val);
                query.addBindValue(QString(val.c_str()));
                val = doc.getInstanceCreationDate();
                t.setDate(QDate::fromString(val.c_str(), "yyyyMMdd"));
                val = doc.getInstanceCreationTime();
                t.setTime(QTime::fromString(QString(val.c_str()).left(6), "hhmmss"));
                query.addBindValue(t.toString("yyyy-MM-dd hh:mm:ss"));
                val = doc.getContentDate();
                t.setDate(QDate::fromString(val.c_str(), "yyyyMMdd"));
                val = doc.getContentTime();
                t.setTime(QTime::fromString(QString(val.c_str()).left(6), "hhmmss"));
                query.addBindValue(t.toString("yyyy-MM-dd hh:mm:ss"));
                query.addBindValue((doc.getCompletionFlag()==DSRTypes::CF_Complete)?QObject::tr("Yes"):QObject::tr("No"));
                query.addBindValue((doc.getVerificationFlag()==DSRTypes::VF_Verified)?QObject::tr("Yes"):QObject::tr("No"));
                query.addBindValue(QObject::tr("No"));
                query.addBindValue(m_srcDir.mid(m_srcDir.lastIndexOf("/")+1) + "/" + f.mid(m_srcDir.size()+1));
                if (query.exec()) {
                    emit resultReady(true, "Import Ok.");
                } else {
                    emit resultReady(false, query.lastError().text());
                }
            } else {
                emit resultReady(false, cond.text());
            }
        }
    }
}
